////////////////////////////////////////////////////////////////////////////////
//
//  ADOBE SYSTEMS INCORPORATED
//  Copyright 2008 Adobe Systems Incorporated
//  All Rights Reserved.
//
//  NOTICE: Adobe permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////


package net.asciiworks.tlf.supportClasses {

    import mx.core.UIComponentGlobals;
    import mx.core.mx_internal;

    import spark.components.supportClasses.DropDownListBase;
    import spark.components.supportClasses.ItemRenderer;
    import spark.components.supportClasses.TextBase;
    import spark.utils.LabelUtil;

    use namespace mx_internal;

    /**
     *  The DropDownList control contains a drop-down list
     *  from which the user can select a single value.
     *  Its functionality is very similar to that of the
     *  SELECT form element in HTML.
     *
     *  <p>The DropDownList control consists of the anchor button,
     *  prompt area, and drop-down-list,
     *  Use the anchor button to open and close the drop-down-list.
     *  The prompt area displays a prompt String, or the selected item
     *  in the drop-down-list.</p>
     *
     *  <p>When the drop-down list is open:</p>
     *  <ul>
     *    <li>Clicking the anchor button closes the drop-down list
     *      and commits the currently selected data item.</li>
     *    <li>Clicking outside of the drop-down list closes the drop-down list
     *      and commits the currently selected data item.</li>
     *    <li>Clicking on a data item selects that item and closes the drop-down list.</li>
     *    <li>If the <code>requireSelection</code> property is <code>false</code>,
     *      clicking on a data item while pressing the Control key deselects
     *      the item and closes the drop-down list.</li>
     *  </ul>
     *
     *  <p><b>Note: </b>The Spark list-based controls (the Spark ListBase class and its subclasses
     *  such as ButtonBar, ComboBox, DropDownList, List, and TabBar) do not support the BasicLayout class
     *  as the value of the <code>layout</code> property.
     *  Do not use BasicLayout with the Spark list-based controls.</p>
     *
     *  <p>The DropDownList control has the following default characteristics:</p>
     *  <table class="innertable">
     *     <tr><th>Characteristic</th><th>Description</th></tr>
     *     <tr><td>Default size</td><td>112 pixels wide and 21 pixels high</td></tr>
     *     <tr><td>Minimum size</td><td>112 pixels wide and 21 pixels high</td></tr>
     *     <tr><td>Maximum size</td><td>10000 pixels wide and 10000 pixels high</td></tr>
     *     <tr><td>Default skin class</td><td>spark.skins.spark.DropDownListSkin</td></tr>
     *  </table>
     *
     *  @mxml <p>The <code>&lt;s:DropDownList&gt;</code> tag inherits all of the tag
     *  attributes of its superclass and adds the following tag attributes:</p>
     *
     *  <pre>
     *  &lt;s:DropDownList
     *    <strong>Properties</strong>
     *    prompt=""
     *    typicalItem="null"
     *
     *    <strong>Events</strong>
     *    closed="<i>No default</i>"
     *    open="<i>No default</i>"
     *  /&gt;
     *  </pre>
     *
     *  @see spark.skins.spark.DropDownListSkin
     *  @see spark.components.supportClasses.DropDownController
     *
     *  @includeExample examples/DropDownListExample.mxml
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public class ColorList extends DropDownListBase {

        //--------------------------------------------------------------------------
        //
        //  Constructor
        //
        //--------------------------------------------------------------------------

        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function ColorList() {
            super();
        }

        //--------------------------------------------------------------------------
        //
        //  Skin parts
        //
        //--------------------------------------------------------------------------    

        //----------------------------------
        //  labelDisplay
        //----------------------------------

        [SkinPart(required="false")]

        /**
         *  An optional skin part that holds the prompt or the text of the selected item.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public var labelDisplay:ItemRenderer;

        //--------------------------------------------------------------------------
        //
        //  Variables
        //
        //--------------------------------------------------------------------------

        private var labelChanged:Boolean = false;

        private var labelDisplayExplicitWidth:Number;

        private var labelDisplayExplicitHeight:Number;

        private var sizeSetByTypicalItem:Boolean;

        //--------------------------------------------------------------------------
        //
        //  Overridden properties
        //
        //--------------------------------------------------------------------------

        //----------------------------------
        //  baselinePosition
        //----------------------------------

        /**
         *  @private
         */
        override public function get baselinePosition():Number {
            return getBaselinePositionForPart(labelDisplay);
        }

        //--------------------------------------------------------------------------
        //
        //  Properties
        //
        //--------------------------------------------------------------------------

        //----------------------------------
        //  prompt
        //----------------------------------

        /**
         *  @private
         */
        private var _prompt:String = "";

        /**
         *  The prompt for the DropDownList control.
         *  The prompt is a String that is displayed in the
         *  DropDownList when <code>selectedIndex</code> = -1.
         *  It is usually a String such as "Select one...".
         *  Selecting an item in the drop-down list replaces the
         *  prompt with the text from the selected item.
         *
         *  @default ""
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get prompt():String {
            return _prompt;
        }

        /**
         *  @private
         */
        public function set prompt(value:String):void {
            if (_prompt == value)
                return;

            _prompt = value;
            labelChanged = true;
            invalidateProperties();
        }

        //--------------------------------------------------------------------------
        //
        //  Overridden Properties
        //
        //--------------------------------------------------------------------------

        /**
         *  Layouts use the preferred size of the <code>typicalItem</code>
         *  when fixed row or column sizes are required, but a specific
         *  <code>rowHeight</code> or <code>columnWidth</code> value is not set.
         *  Similarly virtual layouts use this item to define the size
         *  of layout elements that have not been scrolled into view.
         *
         *  <p>The container  uses the typical data item, and the associated item renderer,
         *  to determine the default size of the container children.
         *  By defining the typical item, the container does not have to size each child
         *  as it is drawn on the screen.</p>
         *
         *  <p>Setting this property sets the <code>typicalLayoutElement</code> property
         *  of the layout.</p>
         *
         *  <p>Restriction: if the <code>typicalItem</code> is an IVisualItem, it must not
         *  also be a member of the data provider.</p>
         *
         *  <p>Note: Setting <code>typicalItem</code> overrides any explicit width or height
         *  set on the <code>labelDisplay</code> skin part. </p>
         *
         *  @default null
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        override public function set typicalItem(value:Object):void {
            super.typicalItem = value;
            invalidateSize();
        }

        //--------------------------------------------------------------------------
        //
        //  Overridden methods
        //
        //--------------------------------------------------------------------------

        /**
         *  @private
         */
        override protected function commitProperties():void {
            super.commitProperties();

            if (labelChanged) {
                labelChanged = false;
                updateLabelDisplay();
            }
        }

        /**
         *  @private
         */
        override protected function partAdded(partName:String, instance:Object):void {
            super.partAdded(partName, instance);

            if (instance == labelDisplay) {
                labelChanged = true;
                invalidateProperties();
            }
        }

        /**
         *  @private
         */
        override protected function measure():void {
            // If typicalItem is set, then use it for measurement
            if (labelDisplay && typicalItem != null) {
                // Save the labelDisplay's dimensions in case we clear out typicalItem
                if (!sizeSetByTypicalItem) {
                    labelDisplayExplicitWidth = labelDisplay.explicitWidth;
                    labelDisplayExplicitHeight = labelDisplay.explicitHeight;
                    sizeSetByTypicalItem = true;
                }

                labelDisplay.explicitWidth = NaN;
                labelDisplay.explicitHeight = NaN;

                // Swap in the typicalItem into the labelDisplay
                updateLabelDisplay(typicalItem);
                UIComponentGlobals.layoutManager.validateClient(skin, true);

                // Force the labelDisplay to be sized to the measured size
                labelDisplay.width = labelDisplay.measuredWidth;
                labelDisplay.height = labelDisplay.measuredHeight;

                // Set the labelDisplay back to selectedItem
                updateLabelDisplay();
            } else if (sizeSetByTypicalItem && typicalItem == null) {
                // Restore the labelDisplay to its original size
                labelDisplay.width = labelDisplayExplicitWidth;
                labelDisplay.height = labelDisplayExplicitHeight;
                sizeSetByTypicalItem = false;
            }

            super.measure();
        }

        /**
         *  @private
         *  Called whenever we need to update the text passed to the labelDisplay skin part
         */
        // TODO (jszeto): Make this protected and make the name more generic (passing data to skin) 
        override mx_internal function updateLabelDisplay(displayItem:* = undefined):void {
            if (labelDisplay) {
                if (displayItem == undefined)
                    displayItem = selectedItem;
                if (displayItem != null && displayItem != undefined) {
                    labelDisplay.data = displayItem;
                    labelDisplay.visible = true;
                }
                if (!displayItem)
                    labelDisplay.visible = false;
            }
        }

    }

}
